package com.example.h9iserver.service.impl;

import com.example.h9iserver.common.BusinessException;
import com.example.h9iserver.common.ExceptionCodeConstants;
import com.example.h9iserver.domain.Authority;
import com.example.h9iserver.domain.CustomUserDetails;
import com.example.h9iserver.domain.Role;
import com.example.h9iserver.domain.User;
import com.example.h9iserver.mapper.AuthorityMapper;
import com.example.h9iserver.mapper.RoleMapper;
import com.example.h9iserver.mapper.UserMapper;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 用户详情服务
 *
 * @author harry
 * @公众号 Harry技术
 */
@Service
@RequiredArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {
    private final UserMapper userMapper;
    private final RoleMapper roleMapper;
    private final AuthorityMapper authorityMapper;
    @Override
    public CustomUserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 获取登录用户信息
        User user = userMapper.selectByUsername(username);
        // 用户不存在
        if (user == null) {
            throw new BusinessException(ExceptionCodeConstants.AUTH_NOUSER);
        }
        Long userId = user.getId();
        // 获取角色
        Set<Role> roleSet = roleMapper.listRoleKeyByUserId(userId);
        Set<Authority> authoritySet = new HashSet<>();
        if (CollectionUtils.isNotEmpty(roleSet)) {
            // 获取权限
            authoritySet = getAuthoritieSet(roleSet);
        }
        return new CustomUserDetails(user.getUsername(), user.getPassword(), getRoleCodeSet(roleSet), getAuthorityCodeSet(authoritySet), true, user);
    }

    private Set<Authority> getAuthoritieSet(Set<Role> roleSet) {
        List<Long> roleIdList = roleSet.stream().map(Role::getId).toList();
        return authorityMapper.listAuthorityKeyByRoleIdList(roleIdList);
    }

    private static Set<String> getRoleCodeSet(Set<Role> roleSet) {
        return roleSet.stream().map(Role::getCode).collect(Collectors.toSet());
    }

    private static Set<String> getAuthorityCodeSet(Set<Authority> authoritySet) {
        return authoritySet.stream().map(Authority::getCode).collect(Collectors.toSet());
    }
}